﻿#include "mainwindow.h"
#include <QtGui>
#include <QCoreApplication>
#include <QFile>
#include <QFileInfo>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkProxy>
#include <QUrl>

MainWindow::MainWindow(QWidget *parent)
	: QMainWindow(parent)
{
	readSettings();
	QWidget *mainWidget = new QWidget();
	QLabel *urlLabel = new QLabel("  Url:");
	QLabel *pathLabel = new QLabel(" Save to:");
	urlLineEdit = new QLineEdit();
	pathLineEdit = new QLineEdit();
	pathLineEdit->setText(savePath);
	logTextEdit = new QTextEdit();
	connect(logTextEdit, SIGNAL(textChanged()),SLOT(scrollLog()));
	v_min = new QSpinBox();	v_min->setMinimum(1); v_min->setMaximum(999); v_min->setValue(volumeMin.toInt());
	v_max = new QSpinBox();	v_max->setMinimum(1); v_max->setMaximum(999); v_max->setValue(volumeMax.toInt());
	downloadButton = new QPushButton(tr("Download"));
	connect(downloadButton, SIGNAL(clicked()), this, SLOT(getJournalInfo()));
	stopButton = new QPushButton(tr("Stop"));
	stopButton->setDisabled(true);
	stopButton->setMaximumWidth(40);
	connect(stopButton, SIGNAL(clicked()), this, SLOT(stop()));
	QPushButton *helpButton = new QPushButton(tr("?"));
    helpButton->setMaximumWidth(20);
	connect(helpButton, SIGNAL(clicked()), this, SLOT(help()));
	indexBox = new QCheckBox("Only index");
	progressBar = new QProgressBar();
	progressBar->setFormat("%p%  %v of %m");
	QHBoxLayout *urlLayout = new QHBoxLayout;
	urlLayout->setMargin(0);
	urlLayout->addWidget(urlLabel);
	urlLayout->addWidget(urlLineEdit);
	urlLayout->addWidget(v_min);
	urlLayout->addWidget(v_max);
	urlLayout->addWidget(indexBox);
	urlLayout->addWidget(helpButton);
	QHBoxLayout *pathLayout = new QHBoxLayout;
	pathLayout->setMargin(0);
	pathLayout->addWidget(pathLabel);
	pathLayout->addWidget(pathLineEdit);
	pathLayout->addWidget(downloadButton);
	pathLayout->addWidget(stopButton);
	QVBoxLayout *mainLayout = new QVBoxLayout;
	mainLayout->addLayout(urlLayout);
	mainLayout->addLayout(pathLayout);
	mainLayout->addWidget(progressBar);
	mainLayout->addWidget(logTextEdit);
	mainLayout->setMargin(1);
    mainWidget->setLayout(mainLayout);
	setWindowTitle(tr("Journal Downloader"));
	this->setCentralWidget(mainWidget);
	this->resize(QSize(700, 480));
	this->move(290,260);
	urlLineEdit->setFocus();
	downloadBar = new QProgressBar();
	downloadBar->setFixedHeight(13);
	downloadBar->setFormat("%p%  %v/%m bytes");
	downloadBar->setMinimumWidth(300);
	downloadLabel = new QLabel("Ready");
	downloadLabel->setAlignment(Qt::AlignRight);
	statusBar()->addWidget(downloadBar);
	statusBar()->addWidget(downloadLabel,10);
	statusBar()->setContentsMargins(0,0,0,0);
	statusBar()->setFixedHeight(20);
	connect(urlLineEdit, SIGNAL(textChanged(QString)),SLOT(urlChanged(QString)));
	urlLineEdit->setText(journalUrl);
	connect(&qnam_volumes, SIGNAL(finished(QNetworkReply*)),SLOT(processVolumes(QNetworkReply*)));
	connect(&qnam_volumesIW, SIGNAL(finished(QNetworkReply*)),SLOT(processVolumesIW(QNetworkReply*)));
	connect(&qnam_issuesSL, SIGNAL(finished(QNetworkReply*)),SLOT(processIssuesSL(QNetworkReply*)));
	connect(&qnam_issuesSD, SIGNAL(finished(QNetworkReply*)),SLOT(processIssuesSD(QNetworkReply*)));
	connect(&qnam_articles, SIGNAL(finished(QNetworkReply*)),SLOT(Download(QNetworkReply*)));
	connect(&time_out, SIGNAL(timeout()), SLOT(abortSD()));

	qnam_issuesSD.setCookieJar(cookiesJar);
}
void MainWindow::resetUI() {
	downloadButton->setText("Download");
	downloadButton->setEnabled(true);
	stopButton->setDisabled(true);
	setWindowTitle(tr("Journal Downloader"));
	urlLineEdit->setEnabled(true);
	pathLineEdit->setEnabled(true);
}
void MainWindow::getJournalInfo()
{
	QSettings proxySettings("settings.ini", QSettings::IniFormat);
	QNetworkProxy proxy;
	proxy.setType(QNetworkProxy::HttpProxy);
    proxy.setHostName(proxySettings.value("Proxy/HostName", "").toString());
	proxy.setPort(proxySettings.value("Proxy/Port", 3128).toInt());
    proxy.setUser(proxySettings.value("Proxy/User", "").toString());
    proxy.setPassword(proxySettings.value("Proxy/Password", "").toString());
	if(proxySettings.value("Proxy/Enabled", 0).toBool()) qnam_articles.setProxy(proxy);
	//QNetworkProxy::setApplicationProxy(proxy);

	savePath = pathLineEdit->text();
	if(savePath.at(savePath.length()-1) == '/')	savePath.remove(savePath.lastIndexOf('/'),1);
	journalUrl = urlLineEdit->text();
	QDir dir;
	dir.mkpath(savePath);
	QFile file(QString(savePath+"/index_temp.html"));
	file.remove();
	listOfArticlePages.clear();
	listOfArticleUrls.clear();
	listOfIssueUrls.clear();
	listOfPaths.clear();
	issueList.clear();
	totalSize = 0; totalErrors = 0;
	is_stopped = false;
	downloadButton->setDisabled(true);
	downloadButton->setText("wait...");
	stopButton->setEnabled(true);
	urlLineEdit->setDisabled(true);
	pathLineEdit->setDisabled(true);
	setWindowTitle(tr("Downloading..."));
	current_volume = "0";
	url = QUrl::fromEncoded(journalUrl.toLocal8Bit());
	if(journalUrl.contains("springerlink")) {
		site = "springer";
		if(journalUrl.at(journalUrl.length()-1) != '/')	journalUrl += "/";
		url = QUrl::fromEncoded(journalUrl.toLocal8Bit());
		qnam_volumes.get(QNetworkRequest(url));
	}
	else if(journalUrl.contains("informaworld")) {
		site = "informaworld";
		qnam_volumesIW.get(QNetworkRequest(url));
	}
	else if(journalUrl.contains("sciencedirect")) {
		site = "sciencedirect";
		qnam_issuesSD.get(QNetworkRequest(url));
	}
	else {
		QMessageBox::warning(this, "Error", "Invalid url");
		resetUI();
	}
}
void MainWindow::processVolumes(QNetworkReply *reply)
{
	downloadLabel->setText("Parsing volumes...");
	issueList.clear();
	QUrl url = reply->url();
	if (reply->error()) {
		logTextEdit->append(QString("<b><font color=\"#FF0000\">Download of %1 failed: %2</font><b>").
				arg(url.toEncoded().constData()).arg(qPrintable(reply->errorString())));
	} else {
		QByteArray data = reply->readAll();
		reply->deleteLater();
		if(current_volume == "0"){
			QString datav = data;
			datav.remove(0, datav.indexOf("selector\">Volume", 0)+17);
			datav.insert(datav.indexOf("</span>"), "|||");
			while(datav.contains("selector\">Volume")) {
				datav.remove(datav.indexOf("</span>"), datav.indexOf("selector\">Volume", 0)+17-datav.indexOf("</span>"));
				datav.insert(datav.indexOf("</span>"), "|||");
			}
			//datav.remove(datav.indexOf("</span>"), datav.indexOf("selector current\">Volume", 0)+25-datav.indexOf("</span>"));
			datav.remove(datav.lastIndexOf("|||"), datav.length());
			while(datav.contains(" /"))
				datav.remove(datav.indexOf(" /"), datav.indexOf(")", datav.indexOf(" /"))+1-datav.indexOf(" /"));
			volumeList = datav.split("|||");
			while(volumeList.last() != v_min->text())
				volumeList.removeLast();
			while(volumeList.first() != v_max->text())
				volumeList.removeFirst();
			logTextEdit->insertPlainText(QString("%1 volumes:").arg(volumeList.count()));
			current_volume = volumeList.last();
			QNetworkReply *reply;
			reply = qnam_volumes.get(QNetworkRequest(QUrl(journalUrl+current_volume+"/")));
			return;
		}
		logTextEdit->insertPlainText(QString(" %1").arg(current_volume));
		int index = data.indexOf("/\">Number", 0);
		data.replace(index, 9, "|||");
		data.remove(0, data.lastIndexOf("/", index-1)+1);
		while (data.contains(">Number ") || data.contains(">Numbers ")) {
			index = data.indexOf("/\">Number", 0);
			data.remove(data.lastIndexOf("|||",index)+3, data.lastIndexOf("/", index-1)-2-data.lastIndexOf("|||",index));
			data.replace(data.indexOf("/\">Number", 0), 9, "|||");
		}
		data.remove(data.lastIndexOf("|||"), data.length());
		QByteArray str;
		str.insert(0, "=");
		data.replace("|||", str);
		issueList << data.split('=');
		for(int i = issueList.count()-1; i >= 0; i--)
			listOfIssueUrls << journalUrl+current_volume+"/"+issueList.at(i)+"/";
		volumeList.removeLast();
		if(volumeList.count() > 0) {
			current_volume = volumeList.last();
			QNetworkReply *reply;
			reply = qnam_volumes.get(QNetworkRequest(QUrl(journalUrl+current_volume+"/")));
			progressBar->setMaximum(v_max->value()-v_min->value());
			progressBar->setValue(v_max->value()-v_min->value()-volumeList.count());
		}
		else {
			logTextEdit->append("\nProcessing issues...");
			current_issue = 0;
			QNetworkReply *reply2;
			reply2 = qnam_issuesSL.get(QNetworkRequest(QUrl(listOfIssueUrls.at(current_issue))));
			progressBar->setMaximum(listOfIssueUrls.count());
			progressBar->setValue(current_issue);
		}
	}
}
void MainWindow::processIssuesSL(QNetworkReply *reply)
{
	downloadLabel->setText("Parsing issues...");
	QUrl url = reply->url();
	QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
	if (reply->error()) {
		logTextEdit->append(QString("<b><font color=\"#FF0000\">Download of %1 failed: %2</font></b>").
				arg(url.toEncoded().constData()).arg(qPrintable(reply->errorString())));
		totalErrors++;
	}
	else if (!redirectionTarget.isNull()) {
		QUrl newUrl = url.resolved(redirectionTarget.toUrl());
		 reply->deleteLater();
		 qnam_issuesSL.get(QNetworkRequest(newUrl));
		 //qDebug() << "redirected";
		 return;
	}
	else {
		page = reply->readAll();
		QFile file(QString(savePath+"/index_temp.html"));
		file.open(QFile::Append | QFile::Text);
		file.write(page);
		file.close();
		logTextEdit->append(QString("<i>%1</i> successfully processed\n").arg(url.toEncoded().constData()));
		if(page.contains("title=\"Next\">Next&#xa0;&#x3e;</a>")) {
			QString nextlink = page;
			nextlink.remove(page.indexOf("title=\"Next\">Next&#xa0;&#x3e;</a>")-2, page.length());
			nextlink.replace(0, nextlink.lastIndexOf("\"")+1, "http:\//www.informaworld.com");
			nextlink.replace("&#x26;", "&");
			listOfIssueUrls.insert(current_issue+1, nextlink.toLocal8Bit());
		}
	}
	reply->deleteLater();
	current_issue++;
	progressBar->setValue(current_issue);
	progressBar->setMaximum(listOfIssueUrls.count());
	if(current_issue < listOfIssueUrls.count()) {
		QNetworkReply *reply;
		reply = qnam_issuesSL.get(QNetworkRequest(QUrl(listOfIssueUrls.at(current_issue))));
	}
	else {
		logTextEdit->append("<b>Completed</b>");
		setWindowTitle(tr("Downloading articles..."));
		parse();
	}
}
void MainWindow::processIssuesSD(QNetworkReply *reply)
{
	time_out.stop();
	downloadLabel->setText("Parsing issues...");
	if (reply->error() && (reply->error() != QNetworkReply::OperationCanceledError)) {
		logTextEdit->append(QString("<b><font color=\"#FF0000\">Download of %1 failed: %2</font></b>").
				arg(reply->url().toEncoded().constData()).arg(qPrintable(reply->errorString())));
		totalErrors++;
	} else if (reply->error() == QNetworkReply::NoError) {
		page = reply->readAll();
		if (page.contains("No next volume/issue"))
			is_stopped = true;
		else {
			QFile file(QString(savePath+"/index_temp.html"));
			file.open(QFile::Append | QFile::Text);
			file.write(page);
			file.close();
			nextlink = page;
			if(page.contains("Next page")) nextlink.remove(0, nextlink.indexOf("href=",nextlink.indexOf("title=\"Next page\""))+6);
			else nextlink.replace(0, nextlink.indexOf("Next volume/issue")+46,"http://www.sciencedirect.com");
			nextlink.remove(nextlink.indexOf("\""),nextlink.length());
            page.remove(0, page.indexOf("<title>")+7);
            page.remove(page.indexOf(" | ScienceDirect.com</title"),page.length());
            logTextEdit->append("<i>" + page +"</i> "+QString(QChar(0x2713)));
		}
	}
	reply->deleteLater();
	if(!is_stopped) {
		replySD = qnam_issuesSD.get(QNetworkRequest(QUrl::fromEncoded(nextlink.toLocal8Bit())));
		time_out.start(15*1000);
		connect(replySD, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(downloadProgress(qint64,qint64)));
	}
	else {
		is_stopped = false;
		logTextEdit->append("<b>Completed</b>");
		setWindowTitle(tr("Downloading articles..."));
		parse();
	}
}
void MainWindow::abortSD()
{
	replySD->abort();
	logTextEdit->append(QString("<b><font color=\"#FF0000\">Timeout error. Retrying...</font></b>"));
}
void MainWindow::processVolumesIW(QNetworkReply *reply)
{
	downloadLabel->setText("Parsing volumes...");
	QUrl url = reply->url();
	QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
	if (reply->error()) {
		logTextEdit->append(QString("<b><font color=\"#FF0000\">Download of %1 failed: %2</font></b>").
				arg(url.toEncoded().constData()).arg(qPrintable(reply->errorString())));
		totalErrors++;
	}
	else if (!redirectionTarget.isNull()) {
		QUrl newUrl = url.resolved(redirectionTarget.toUrl());
		 reply->deleteLater();
		 qnam_volumesIW.get(QNetworkRequest(newUrl));
		 return;
	}
	else {
		page = reply->readAll();
		QFile file(QString(savePath+"/issues.html"));
		file.open(QFile::Append | QFile::Text);
		file.write(page);
		file.close();
		logTextEdit->append(QString("<i>%1</i> successfully processed\n").arg(url.toEncoded().constData()));
	}
	QString line;
	QFile file(QString(savePath+"/issues.html"));
	file.open(QFile::ReadOnly | QFile::Text);
	QTextStream in(&file);
	in.setCodec("utf-8");
	while (!in.atEnd()){
		line = in.readLine(0);
		if ( line.contains("./title~db=all~content=g") && line.contains("Click to view"))
		{
			line.replace(0, line.indexOf("./title~")+1, "http:\/\/www.informaworld.com/smpp");
			line.remove(line.indexOf("\""), line.length());
			listOfIssueUrls << line;
		}
	}
	file.close();
	QFile::remove(QString(savePath+"/issues.html"));
	logTextEdit->append("\nProcessing issues...");
	current_issue = 0;
	QNetworkReply *reply2;
	reply2 = qnam_issuesSL.get(QNetworkRequest(QUrl(listOfIssueUrls.at(current_issue))));
	progressBar->setMaximum(listOfIssueUrls.count());
	progressBar->setValue(current_issue);
}
void MainWindow::scrollLog()
{
	logTextEdit->ensureCursorVisible();
	//logTextEdit->verticalScrollBar()->setMinimum(logTextEdit->verticalScrollBar()->maximum());
}
void MainWindow::urlChanged(QString string)
{
	journalUrl = string;
	if(journalUrl.contains("springerlink"))
		site = "springer";
	else if(journalUrl.contains("informaworld"))
		site = "informaworld";
	else if(journalUrl.contains("sciencedirect"))
		site = "sciencedirect";
	v_min->setVisible(journalUrl.contains("springerlink"));
	v_max->setVisible(journalUrl.contains("springerlink"));
}
void MainWindow::selectUrl()
{
	urlLineEdit->selectAll();
}
void MainWindow::parse()
{
	logTextEdit->insertPlainText("\n\nStart parsing indexes...");
	QString line, line2, issue, volume, year, content, article, pages, author, year_min = "0000";
	QFile file(QString(savePath+"/index_temp.html"));
	file.open(QFile::ReadOnly);
	QTextStream in(&file);
	in.setCodec("utf-8");
	int st, end;
	while (!in.atEnd() && (site == "springer")){
		line = in.readLine(0);
		if ( line.contains("View the volume of this issue"))
		{
			st = line.indexOf("Number");
			end = line.indexOf(" /", st+5);
			issue = line;
			issue.remove(end,issue.length()-end);
			issue.remove(0, line.indexOf(' ', st)+1);
			volume = line;
			volume.remove(line.indexOf("</a>, Number"),line.length()-line.indexOf("</a>, Number"));
			volume.remove(0, line.indexOf("\">Volume")+9);
			year = line;
			year.remove(0, year.length()-5);
			year.remove(4,1);
			line.remove(0, line.indexOf("\">Volume")+2);
			line.remove("</a>");
			content += "</table>\n";
			content += "<h3>"+line.remove(line.length()-1,1)+"</h3>\n";
			//content += "<h3>"+year+" Volume="+volume+", Issue="+issue+"</h3>\n";
			content += "<table cellpadding=\"3\" cellspacing=\"1\" border=\"1px\">\n";
			if (year_min == "0000") year_min = year;
		}
		if (line.contains("primitive contribution journalArticle")/* && line.contains("Download PDF")*/) {
			line.replace(0, line.indexOf("Tag\">")+5, "<tr><td>");
			pages = line;
			pages.remove("<tr><td>");
			pages.remove(pages.indexOf("</p>"), pages.length()-pages.indexOf("</p>"));
			listOfArticlePages << pages;
			line.replace(line.indexOf("</p>",0),line.indexOf("<p class=\"title\">")+17-line.indexOf("</p>",0),"</td><td>");
			line.remove("</a>");
			line.replace("</p><p class=\"authors\">", "</a></td><td>");
			while (line.contains("View content where Author")) {
				st = line.indexOf("<a title=\"View content where Author");
				line.remove(st, line.indexOf("\">", st)-st+2);
			}
			line.replace("</p><ul class=\"resources fulltextResources\">","</td></tr>");
			article = line;
			article.remove(0, article.indexOf("<a href=")+9);
			article.remove(article.indexOf("/\">"), article.length());
			article.remove("/content/");
			//article.replace("/content","http://www.springerlink.com/content");
			//article.append("fulltext.pdf");
			listOfArticleUrls << "http://www.springerlink.com/content/"+article+"/fulltext.pdf";
			listOfPaths << year+" Volume " +volume+"/"+issue+"/";
			line.replace(line.indexOf("/\">",line.indexOf("/content/")),1,".pdf");
			//line.replace("/content", year+" Volume " +volume+"/"+issue);
			line.replace(line.indexOf("/content"), line.indexOf(".pdf")-line.indexOf("/content"), year+" Volume " +volume+"/"+issue+"/"+pages);
			content += line;
		}
	}
	while (!in.atEnd() && (site == "sciencedirect")){
		line = in.readLine(0);
		if (line.contains("Issue") && line.contains("Volume") && line.contains("Page") && !line.contains("title"))
		{
			line.remove(0, line.indexOf("Volume"));
			st = line.indexOf("Issue");
			end = line.indexOf(",", st+5);
			issue = line;
			issue.remove(end,issue.length()-end);
			issue.remove(0, issue.indexOf(" ", issue.indexOf("Issue"))+1);
			volume = line;
			volume.remove(line.indexOf(","),line.length()-line.indexOf(","));
			volume.remove(0, line.indexOf(" ")+1);
			year = line;
			year.remove(line.indexOf(")"),50);
			year.remove(0, year.length()-4);
			//content += "Volume="+volume+"; Issue="+issue+"; Year=" + year+ "\n";
			content += "</table>\n<h3>"+line+"</h3>\n";
			in.readLine(0);
			line2 = in.readLine(0);
			line2.remove("			  ");
			if (!line2.contains("nbsp")) { line2.replace("<br>"," "); content += line2; }
			content += "<table cellpadding=\"3\" cellspacing=\"1\" border=\"1px\">\n";
			//content += "<table cellpadding=\"3\" cellspacing=\"1\" border=\"1px\">\n";
			if (year_min == "0000") year_min = year;
		}
        if (line.contains("science?_ob=MiamiImageURL") && line.contains("access the full text")) {
			article = line;
			article.remove(0, article.lastIndexOf("<a href=")+9);
            article.remove(article.indexOf("-main.pdf")+9, article.length());
			listOfArticleUrls << article;
			line.replace(0, line.indexOf("<a href="), "<tr><td>");
			line.remove("<span style=\"font-weight : bold ;\">");
            line.remove(line.indexOf("</span></a>"), line.indexOf("<br><i>")-line.indexOf("</span></a>"));
			line.replace("<br><i>", "</a></td><td>");
			line.replace("</i><br>", "</td><td>");
			line.replace(line.indexOf("<div class=\"txt\">"),line.length(), "</td></tr>\n");
			line.remove("<br>");
			pages = line;
			pages.remove(0, pages.indexOf("</a></td><td>")+13);
			pages.remove(pages.indexOf("</td>"), pages.length());
			pages.remove(0, pages.indexOf(" ")+1);
			line.insert(line.indexOf("<tr><td>")+4,"<td>"+pages+"</td>");
			listOfArticlePages << pages;
			listOfPaths << year+" Volume " +volume+"/"+issue+"/";
			line.remove(line.indexOf("</a></td><td>")+4,line.indexOf("</td><td>",line.indexOf("</a></td><td>")+13)-line.indexOf("</a></td><td>")-4);
			line.replace(line.indexOf("http:"),line.indexOf("\">")-line.indexOf("http:"), year+" Volume " +volume+"/"+issue+"/"+pages+".pdf");
			content += line;
		}
	}
	while (!in.atEnd() && (site == "informaworld")){
		line = in.readLine(0);
		if (line.contains("Click to go to publication home") && line.contains("Volume"))
		{
			volume = line.remove(0, line.indexOf("</a>, Volume ")+13);
			issue = "";
			year = "";
			issue.remove("Issue ");
			line = in.readLine(0);
//			if (line == "&#x26;" || line == "-") {
//				issue = issue+"-"+in.readLine(0);
//				year = in.readLine(0);
//			}
//			else year = line;
			in.readLine(0); in.readLine(0);
			line = in.readLine(0);
			content += "</table>\n<h3>Volume "+volume+/*", Issue "+issue+" ("+year+")" +*/ "</h3>\n";
			if (line == "<h2>") {
				line = in.readLine(0);
				content +="<h4>"+line+"</h4>\n";
			}
			content += "<table cellpadding=\"3\" cellspacing=\"1\" border=\"1px\">\n";
			if (year_min == "0000") year_min = year;
		}
		else if (line.contains("title=\"Click to view volume") && line.contains("Volume"))
		{
			volume = line.remove(0, line.indexOf("view volume")+13);
			volume.remove("</a>");
			issue = in.readLine(0);
			issue.remove("Issue ");
			line = in.readLine(0);
			if (line == "&#x26;" || line == "-") {
				issue = issue+"-"+in.readLine(0);
				year = in.readLine(0);
			}
			else year = line;
			in.readLine(0); in.readLine(0);
			line = in.readLine(0);
			content += "</table>\n<h3>Volume "+volume+", Issue "+issue+" ("+year+")</h3>\n";
			if (line == "<h2>") {
				line = in.readLine(0);
				content +="<h4>"+line+"</h4>\n";
			}
			content += "<table cellpadding=\"3\" cellspacing=\"1\" border=\"1px\">\n";
			if (year_min == "0000") year_min = year;
		}
		if (line.contains("frm=titlelink") && line.contains("Click to view this record")) {
			article = line;
			article.remove(0, article.indexOf("target=\"")+10);
			article.remove("</a></b>");
			if(article.contains("<img"))
				article.remove(article.indexOf("<img"),
							   article.indexOf(">", article.indexOf("<img"))+2-article.indexOf("<img"));
			if(in.readLine(0) == "</a></b>") in.readLine(0);
			author = in.readLine(0);
			if(author.contains("<i>") && !author.contains("Page")) {
				author.remove("<i>");
				author.remove(" </i><br />");
				author.replace("&#xa0;", " ");
			}
			else if (author.contains("Page")) { pages = author.remove("Pages "); pages.remove("Page "); author = "";}
			else author = "";
			line = in.readLine(0);
			if(line.contains("Page") && !line.contains("Full Text PDF")) {
				pages = line.remove("Pages ");
				pages.remove("Page ");
				line = in.readLine(0);
			}
			for(int i = 0; i < 10; i++){
				if(line.contains("Full Text PDF")) {
					i = 10;
					line.remove(line.indexOf("Click to view the PDF")-9, line.length());
					line.replace(0, line.indexOf("/ftinterface"), "http:\//www.informaworld.com/smpp");
					listOfArticleUrls << line;
					pages.replace(" &#x2013; ", "-");
					pages.remove("<br />");
					pages.remove("/");
					listOfArticlePages << pages;
					if(year == "" && issue == "") {
						listOfPaths << "Volume " +volume+"/";
						content += "<tr><td>"+pages+"</td><td><a href=\"Volume "+volume+"/"+pages+".pdf\">"
							+article+"</a></td><td><i>"+author+"</i></td></tr>\n";
					}
					else {
						listOfPaths << year+" Volume " +volume+"/"+issue+"/";
						content += "<tr><td>"+pages+"</td><td><a href=\""+year+" Volume "+volume+"/"+issue+"/"+pages+".pdf\">"
							+article+"</a></td><td><i>"+author+"</i></td></tr>\n";
					}
				}
				line = in.readLine(0);
			}
		}
	}
	content.remove(content.indexOf("</table>",0),8);
	content += "</table>\n</body></html>";
	QString title = savePath;
	if(year_min.toInt() > year.toInt()) { line = year; year = year_min; year_min = line; }
	content.prepend(QString("<html>\n<head>\n\t<title>%1 (%2-%3)</title>\n \
							\t<meta http-equiv=content-type content=\"text/html; charset=utf-8\">\n</head>\n<body>\n\t<h1 align=\"center\">%1 (%2-%3)</h1>")
			.arg(title.remove(0, savePath.lastIndexOf("/")+1)).arg(year_min).arg(year));
	file.remove();

	QFile file2(savePath+"/index.html");
	file2.open(QFile::WriteOnly | QFile::Text);
	QTextStream out2(&file2);
	out2.setCodec("utf-8");
	out2 << content;
	file2.close();
	logTextEdit->insertHtml(QString("  <b>Completed. Total %1 articles</b>\n").arg(listOfArticleUrls.count()));

	if(!indexBox->isChecked()) {
		logTextEdit->insertPlainText("\n\nDownloading of articles...\n");
		current_article = 0;
		while((current_article < listOfArticleUrls.count()) &&
			  QFile::exists(savePath+"/"+listOfPaths.at(current_article)+listOfArticlePages.at(current_article)+".pdf"))
			++current_article;
		if (current_article >= listOfArticleUrls.count()) {
			logTextEdit->append("<b>All articles are downloaded</b><br>");
			resetUI();
		}
		else {
			QString link = listOfArticleUrls.at(current_article);
			QNetworkReply *reply;
			url = QUrl::fromEncoded(link.toLocal8Bit());
			reply = qnam_articles.get(QNetworkRequest(url));
			connect(reply, SIGNAL(downloadProgress(qint64,qint64)),SLOT(downloadProgress(qint64,qint64)));
			progressBar->setMaximum(listOfArticleUrls.count());
			progressBar->setValue(current_article);
		}
	}
}
void MainWindow::Download(QNetworkReply *reply)
{
	if (totalErrors == 0) downloadLabel->setText(QString("Downloaded %1 articles. Size: %2 MB  Errors: %3")
						   .arg(current_article+1).arg(totalSize/1024/1024).arg(totalErrors));
	else downloadLabel->setText(QString("Downloaded %1 articles. Size: %2 MB  <b><font color=\"#FF0000\">Errors: %3</font></b>")
								.arg(current_article+1).arg(totalSize/1024/1024).arg(totalErrors));
	QUrl url = reply->url();
	QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);

	if (reply->error() == QNetworkReply::TimeoutError) {
		logTextEdit->append(QString("\nDownload of %1 failed: %2\n")
			.arg(url.toEncoded().constData()).arg(qPrintable(reply->errorString())));
		logTextEdit->append(QString("<b><font color=\"#FF0000\">Timeout error. Retrying...</font></b>"));
		QNetworkReply *reply;
		reply = qnam_articles.get(QNetworkRequest(url));
		connect(reply, SIGNAL(downloadProgress(qint64,qint64)),SLOT(downloadProgress(qint64,qint64)));
		return;
	}
	else if (reply->error()) {
		logTextEdit->append(QString("\nDownload of %1 failed: %2\n")
			.arg(url.toEncoded().constData()).arg(qPrintable(reply->errorString())));
	}
	else if (!redirectionTarget.isNull()) {
		QUrl newUrl = url.resolved(redirectionTarget.toUrl());
		reply->deleteLater();
		QNetworkReply *reply2;
		reply2 = qnam_articles.get(QNetworkRequest(newUrl));
		connect(reply2, SIGNAL(downloadProgress(qint64,qint64)),SLOT(downloadProgress(qint64,qint64)));
		return;
	}
	else {
		QString suffix = QFileInfo(reply->url().path()).suffix();
		if(suffix.isEmpty()) suffix = "pdf";
		logTextEdit->append(QString("<a href=\"%1\"><i>%2</i></a>&nbsp;&nbsp;%3")
			.arg(savePath+"/"+listOfPaths.at(current_article)+listOfArticlePages.at(current_article)+"."+suffix)
			.arg(listOfPaths.at(current_article)+listOfArticlePages.at(current_article)+"."+suffix)
			.arg(saveToDisk(savePath+"/"+listOfPaths.at(current_article), listOfArticlePages.at(current_article)+"."+suffix, reply)));
	}
	reply->deleteLater();
	current_article++;
	while((current_article < listOfArticleUrls.count()) &&
		  QFile::exists(savePath+"/"+listOfPaths.at(current_article)+listOfArticlePages.at(current_article)+".pdf"))
		++current_article;
	progressBar->setValue(current_article);
	if(current_article < listOfArticleUrls.count() && !is_stopped) {
		QNetworkReply *reply;
		QString link = listOfArticleUrls.at(current_article);
		url = QUrl::fromEncoded(link.toLocal8Bit());
		reply = qnam_articles.get(QNetworkRequest(url));
		connect(reply, SIGNAL(downloadProgress(qint64,qint64)),SLOT(downloadProgress(qint64,qint64)));
	}
	else {
		if(is_stopped) logTextEdit->append("<b>Stopped</b><br>");
		else logTextEdit->append("<b>All articles are downloaded</b><br>");
		resetUI();
	}
}
void MainWindow::downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
{
	downloadBar->setMaximum(bytesTotal);
	downloadBar->setValue(bytesReceived);
}
QString MainWindow::saveFileName(const QUrl &url)
{
	QString path = url.path();
	QString basename = QFileInfo(path).completeBaseName();
	QString suffix = QFileInfo(path).suffix();
	if (basename.isEmpty()) {
		basename = "download";
		suffix = "html";
	}
	if (QFile::exists(basename+"."+suffix)) {
		// already exists, don't overwrite
		int i = 0;
		basename += '.';
		while (QFile::exists(QString(basename + QString::number(i))+"."+suffix))
			++i;

		basename += QString::number(i);
	}
	return basename+"."+suffix;
}
QString MainWindow::saveToDisk(const QString &path, const QString &filename, QIODevice *data)
{
	QDir dir;
	qint64 size;
	dir.mkpath(path);
	QFile file(path+filename);
	if (file.exists() && (file.size() > 1024)) return QString("already exists");
	if (!file.open(QIODevice::WriteOnly)) {
		return QString("<b><font color=\"#FF0000\">couldn't be saved: %1</font></b>").arg(file.errorString());
		totalErrors++;
	}
	file.write(data->readAll());
	size =  file.size();
	totalSize += size;
	if (size < 2048) file.remove();
	file.close();
	if (size < 1024) { totalErrors++; return QString("<b><font color=\"#FF0000\">failed (%1)</font></b>").arg(size);}
	else return QString("saved (%1 KB)").arg(size/1024);
}
void MainWindow::help() {
	QMessageBox::information(this, tr("Help"),
        tr("1) Input link to a journal in the field \"Url\"\n"
		   "2) If \"Only index\" is checked then articles won't be downloaded\n"
		   "3) All files will be saved in the folder entered in field \"Save to\". Name of the last folder must be equal to the journal title\n"
		   "3) Press button \"Download\"\n"
           "4) If button \"Stop\" is pressed then next article won't be downloaded (current downloading will not be interrupted)\n\n"
           "Created by backwar, 2010-2012"

		/*3) Под url есть поле с путем для сохранения статей и индекса. По умолчанию там C:/temp/Journal. Имя последней папки должно соответствовать названию журнала - оно будет использовано в index.html.
		 4) После нажатия на кнопку Download начнется выкачивание страничек с содержимым номеров, все они скидываются в index_temp.html. Потом этот файл обрабатывается и формируется окончательный index.html, а index_temp.html удаляется. Далее автоматически скачиваются все найденные статьи.
			5) Если нажать кнопку Stop, то скачивание следующих страниц/статей прекратится (текущая закачка не прерывается).
			6) В процессе скачивания могут быть ошибки, которые подсвечиваются красным цветом.
			На Шпрингере возможна ошибка Object moved or not found, на СД иногда зависает закачка страничек с содержимым номеров. Если загрузились файлы меньше 1 КБ (явно битые), то они автоматически удаляются. Нужно просто заново запустить скачивание, программа заметит уже скачанные статьи и второй раз загружать их не будет.
			7) Индекс после завершения скачивания надо проверить на внешний вид - из-за неправильных ссылок на сайте могут поползти таблицы - исправлять надо вручную в текстовом редакторе.
			8) После закрытия программы ссылка на журнал, путь для сохранения и диапазон томов сохраняются в файле settings.ini.*/));
}
void MainWindow::readSettings()
{
	QSettings settings("settings.ini", QSettings::IniFormat);
	journalUrl = settings.value("Url", "Enter link to a journal...").toString();
	savePath = settings.value("Path", "d:/library/Journals/JournalName").toString();
	volumeMin = settings.value("VolumeMin", 1).toString();
	volumeMax = settings.value("VolumeMax", 10).toString();
//	if(settings.value("MainWindow/isMaximized", 1).toBool()) this->showMaximized();
//	else this->resize(QSize(1000, 800));
}
void MainWindow::writeSettings()
{
	QSettings settings("settings.ini", QSettings::IniFormat);
	settings.setValue("Url", urlLineEdit->text());
	settings.setValue("Path", pathLineEdit->text());
	settings.setValue("VolumeMin", v_min->value());
	settings.setValue("VolumeMax", v_max->value());
	//settings.setValue("MainWindow/size", this->size());
	//settings.setValue("MainWindow/pos", this->pos());
	//settings.setValue("MainWindow/isMaximized", isMaximized());
}
void MainWindow::closeEvent(QCloseEvent * /*event*/)
{
	writeSettings();
}
MainWindow::~MainWindow()
{

}
